﻿using System;
using System.Net;
using System.Net.Sockets;
using Net.Event;
using Net.Helper;
using Net.Share;
using Net.System;

namespace Net.Server
{
    public class GcpClient : ClientPeerBase 
    {
        /// <summary>
        /// Gcp对象
        /// </summary>
        public IGcp Gcp { get; internal set; }

        public override void ReceiveHandler()
        {
            while (ReceiveList.TryDequeue(out var segment))
            {
                Gcp.Input(segment);
                BufferPool.Push(segment);
                while (Gcp.Receive(out var segment1) > 0)
                {
                    ReceiveHandler(ref segment1);
                    BufferPool.Push(segment1);
                }
            }
        }

        protected override void SendByteData(ISegment buffer)
        {
            Gcp.Send(buffer);
        }

        protected override bool CheckIsConnected()
        {
            if (!Connected)
            {
                var tick = (uint)Environment.TickCount;
                if (tick >= ReconnectTimeout)
                    RemoveClient();
                return false;
            }
            return true;
        }

        public override void OnNetworkTick()
        {
            base.OnNetworkTick();
            Gcp.Update();
        }
    }

    /// <summary>
    /// Udp网络服务器
    /// <para>Player:当有客户端连接服务器就会创建一个Player对象出来, Player对象和XXXClient是对等端, 每当有数据处理都会通知Player对象. </para>
    /// <para>Scene:你可以定义自己的场景类型, 比如帧同步场景处理, mmorpg场景什么处理, 可以重写Scene的Update等等方法实现每个场景的更新和处理. </para>
    /// </summary>
    public class UdpServer<Player, Scene> : ServerUdpBase<Player, Scene> where Player : GcpClient, new() where Scene : SceneBase<Player>, new()
    {
        protected override void AcceptHander(Player client, params object[] args)
        {
            client.Gcp = new Plugins.GcpKernel
            {
                MTU = (ushort)Config.MTU,
                RTO = Config.RTO,
                MTPS = Config.MTPS,
                FlowControl = Config.FlowControl,
                RemotePoint = client.RemotePoint
            };
            client.Gcp.OnSender += (remotePoint, segment) =>
            {
                Server.SendTo(segment.Buffer, segment.Offset, segment.Count, SocketFlags.None, remotePoint);
            };
        }
    }

    /// <summary>
    /// 默认udp服务器，当不需要处理Player对象和Scene对象时可使用
    /// </summary>
    public class UdpServer : UdpServer<GcpClient, SceneBase<GcpClient>> { }

    /// <summary>
    /// Gcp网络服务器
    /// <para>Player:当有客户端连接服务器就会创建一个Player对象出来, Player对象和XXXClient是对等端, 每当有数据处理都会通知Player对象. </para>
    /// <para>Scene:你可以定义自己的场景类型, 比如帧同步场景处理, mmorpg场景什么处理, 可以重写Scene的Update等等方法实现每个场景的更新和处理. </para>
    /// </summary>
    public class GcpServer<Player, Scene> : UdpServer<Player, Scene> where Player : GcpClient, new() where Scene : SceneBase<Player>, new() { }

    /// <summary>
    /// 默认gcp服务器，当不需要处理Player对象和Scene对象时可使用
    /// </summary>
    public class GcpServer : GcpServer<GcpClient, SceneBase<GcpClient>> { }
}